#include "stdafx.h"

#include "Lock.h"
#include <iostream>

using namespace CleverLock;
/////////////////////////////////////////////////////////////////////////
//	CWithLock
/////////////////////////////////////////////////////////////////////////
#ifdef _LINUX_ // linux implement
CWithLock::CWithLock()
{
	pthread_mutexattr_t attr;
	pthread_mutexattr_init(&attr);
	pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE_NP);
	pthread_mutex_init(&m_mutex, &attr);
}

CWithLock::~CWithLock()
{
	pthread_mutex_destroy(&m_mutex);
}

/////////////////////////////////////////////////////////////////////////
void CWithLock::Lock()
{
	pthread_mutex_lock(&m_mutex);
}

void CWithLock::UnLock()
{
	pthread_mutex_unlock(&m_mutex);
}

bool CWithLock::TryLock()
{
	return pthread_mutex_trylock(&m_mutex)==0;
}

#else // windows implement
CWithLock::CWithLock()
{
	InitializeCriticalSection( &m_csAccess );
}

CWithLock::~CWithLock()
{
	DeleteCriticalSection( &m_csAccess );
}

/////////////////////////////////////////////////////////////////////////
void CWithLock::Lock()
{
	EnterCriticalSection(&m_csAccess);
}

void CWithLock::UnLock()
{
	LeaveCriticalSection(&m_csAccess);
}

bool CWithLock::TryLock()
{
	return TryEnterCriticalSection(&m_csAccess);
}

HANDLE	CWithLock::GetOwnerThread()
{
	return m_csAccess.OwningThread; 
}
#endif
/////////////////////////////////////////////////////////////////////////
//	CLock
/////////////////////////////////////////////////////////////////////////
CLock::CLock( CWithLock &door, bool b_lock)
{
	m_pDoor = &door;
	m_bLocked = b_lock;
	if (m_bLocked)
		Lock(*m_pDoor);
}

CLock::~CLock()
{
	if (m_bLocked)
		UnLock(*m_pDoor);
}

/////////////////////////////////////////////////////////////////////////
void CLock::Lock()
{
	if(!m_bLocked)
	{
		m_bLocked = true;
		Lock(*m_pDoor);
	}
}

void CLock::UnLock()
{
	if (m_bLocked)
	{
		m_bLocked = false;
		UnLock(*m_pDoor);
	}
}

bool CLock::TryLock()
{
	if(!m_bLocked)
	{
		if ( m_pDoor->TryLock() )
		{
			m_bLocked = true;
			return true;
		}
		
		return false;
	}

	return true;	
}

void CLock::Lock(CWithLock &door)
{
	door.Lock();
}

void CLock::UnLock(CWithLock &door)
{
	door.UnLock();
}
